package environment;

import java.util.Vector;

import org.newdawn.slick.*;
import org.newdawn.slick.geom.Line;
import org.newdawn.slick.Sound;

public class Dirt extends BasicGame {

	Music musc = null;
	
	Sound sndStp = null;
	Sound sndJmp = null;
	Sound sndDig = null;
	Sound sndBmb = null;

	Image skyImage = null;
	SpriteSheet dirtSheet = null;
	Image dirtBlock = null;
	Image bedrockBlock = null;
	Image gravelBlock = null;
	Image bombBlock = null;
	Guy guy = null;
	public static final int GRID_SCALE = 32;
	public static final int INTERVAL = 8;
	public static final int SCROLL_THRESHOLD = GRID_SCALE;
	public static final int HOLE_HEIGHT = 11;
	int viewportY = 0;
	int viewportOffset = 300;

	
	int dirtT = 0;
	int dirtOffset = 0;
	int [][] dirt = new int[25][25];
	
	int gridWidth = dirt.length;
	int gridHeight = dirt[0].length;
	
	public Vector<Line> debugLines = new Vector<Line>();

	public Dirt(String title) {
		super(title);
	}

	public static void main(String[] args) throws SlickException {
		AppGameContainer app = new AppGameContainer(new Dirt("Dirt"));
		app.setDisplayMode(800, 600, false);
		app.start();
	}

	@Override
	public void init(GameContainer gc) throws SlickException {
		gc.setMinimumLogicUpdateInterval(INTERVAL);
		gc.setMaximumLogicUpdateInterval(INTERVAL + 4);
		gc.setShowFPS(false);
		
		// Load Images
		skyImage = new Image("res/sky4.bmp");
		dirtSheet = new SpriteSheet("res/dirt.png", 8, 8, 1);
		dirtBlock = dirtSheet.getSprite(0, 3).getScaledCopy(GRID_SCALE / 8.0f);
		bedrockBlock = dirtSheet.getSprite(3, 3).getScaledCopy(GRID_SCALE / 8.0f);
		gravelBlock = dirtSheet.getSprite(14, 3).getScaledCopy(GRID_SCALE / 8.0f);
		bombBlock = dirtSheet.getSprite(15, 3).getScaledCopy(GRID_SCALE / 8.0f);

		// Load music
		musc = new Music("res/effect_whats_happening.aif");
		musc.play();
		
		// Load sounds
		sndStp = new Sound("res/step.wav");
		sndJmp = new Sound("res/jump.wav");
		sndDig = new Sound("res/dig.wav");
		sndBmb = new Sound("res/bomb.wav");
		
		guy = new Guy(gc, this, 112, 352);
	}

	@Override
	public void render(GameContainer gc, Graphics g) throws SlickException {
		//Viewport
		int width = gc.getWidth();
		int height = gc.getHeight();
		g.translate(0, -viewportY);
		
		//Render Sky
		g.fillRect(0, viewportY, width, height, skyImage, 0, 0);
		
		//Render Dirt
		for(int x = 0; x < gridWidth; x++) {
			for(int y = 0; y < gridHeight; y++) {
				int drawY = y + (viewportY / GRID_SCALE);

				switch(getGrid(x, y)) {
				case 0:
					gravelBlock.draw(x * GRID_SCALE, drawY * GRID_SCALE);
					break;
				case 1:
					dirtBlock.draw(x * GRID_SCALE, drawY * GRID_SCALE);
					break;
				case 3:
					bedrockBlock.draw(x * GRID_SCALE, drawY * GRID_SCALE);
					break;
				case 4:
					bombBlock.draw(x * GRID_SCALE, drawY * GRID_SCALE);
					break;
				}
			}
		}

		//Render Guy
		guy.render(gc, g);
		
		g.setColor(Color.red);
		for (Line line : debugLines) {
			g.drawLine(line.getX1(), line.getY1(), line.getX2(), line.getY2());
		}
	}
	
	@Override
	public void update(GameContainer gc, int timePassed) throws SlickException { 
		guy.update(gc, timePassed);

		//Move Viewport
		int guyY = guy.getY();
		if (guyY > viewportY + viewportOffset) {
			viewportY += guyY - (viewportY + viewportOffset);
			dirtOffset = viewportY / GRID_SCALE;
			dirtT = dirtOffset % gridHeight; 
			for(int x = 0; x < gridWidth; x++)
				setGrid(x, gridHeight - 1, Math.random() < 0.8 ? 1 : Math.random() < 0.75 ? 0 : 4);
		}
}

	public boolean isMovable(int gridX, int gridY) {
		if(gridX < 0 || gridX >= gridWidth)
			return false;
		int value = getGrid(gridX, gridY - dirtOffset);
		if (value != 0 && value != 4) return false;
		return true;
	}

	public boolean hasBomb(int gridX, int gridY) {
		if(gridX < 0 || gridX >= gridWidth)
			return false;
		if (getGrid(gridX, gridY - dirtOffset) == 4) return true;
		return false;
	}

	public void destroy(int gridX, int gridY) {
		if(gridX < 0 || gridX >= gridWidth)
			return;
		if (getGrid(gridX, gridY - dirtOffset) == 1) setGrid(gridX, gridY - dirtOffset, 0);
		sndDig.play();
	}
	
	private int getGrid(int x, int y) {
		int gridY = (y + dirtT) % gridHeight;
		return dirt[x][gridY];
	}
	
	private void setGrid(int x, int y, int value) {
		int gridY = (y + dirtT) % gridHeight;
		dirt[x][gridY] = value;
	}
}
